<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Set 和 Map 数据结构</title>
</head>

<body>
    <script>
        //Set 数据结构 类似于数组，但是成员的值都是唯一的，没有重复
        const s = new Set();
        [2, 3, 5, 4, 5, 2, 2].forEach(x => s.add(x))
        console.log(s)
        // Set函数可以接受一个数组（或者具有 iterable 接口的其他数据结构）作为参数，用来初始化。
        const set = new Set([1, 2, 3, 4, 4])
        // console.log(set)

        //鉴于以上使用，因此Set 可以用来对数组进行去重
        // [...new Set(array)]

        // 也可以用来去除字符串中的重复字符
        // [... new Set('ababc')].join('')
        new Set('abccabcc')
        // 向 Set 加入值的时候，不会发生类型转换，所以5和"5"是两个不同的值。Set 内部判断两个值是否不同，使用的算法叫做“Same-value-zero equality”，它类似于精确相等运算符（===），主要的区别是向 Set 加入值时认为NaN等于自身，而精确相等运算符认为NaN不等于自身。
        let setNon = new Set();
        let a = NaN;
        let b = NaN;
        setNon.add(a);
        setNon.add(b);
        setNon // Set {NaN}

        // Array.from 方法可以将Set结构转为数组
        const items = new Set([1, 2, 3, 4, 5, 1, 3, 4])
        const array = Array.from(items)
        // 数组去重方法的封装
        function dedupe(array) {
            return Array.from(new Set(array))
        }
        const newArr = dedupe([1, 1, 2, 3, 4, 4, 2])

        // Map JavaScript 的对象（Object）,本质上是键值对的集合（Hash 结构），但是传统上只能用祖父穿当做键，这给她的使用带来了很大的限制。
        // 为了解决这个问题， ES6 提供了 Map 数据结构。 它类似于对象， 也是键值对的集合， 但是“ 键” 的范围不限于字符串， 各种类型的值（ 包括对象） 都可以当作键。 也就是说， Object 结构提供了“ 字符串— 值” 的对应， Map 结构提供了“ 值— 值” 的对应， 是一种更完善的 Hash 结构实现。 如果你需要“ 键值对” 的数据结构， Map 比 Object 更合适。
        const m = new Map();
        const o = {
            p: 'Hello World'
        };

        m.set(o, 'content')
        m.get(o) // "content"
        console.log(m.get(o))

        m.has(o) // true
        m.delete(o) // true
        m.has(o) // false

        const map = new Map([
            ['name', '张三'],
            ['title', 'Author']
        ]);

        map.size // 2
        map.has('name') // true
        map.get('name') // "张三"
        map.has('title') // true
        map.get('title') // "Author"

        // Map构造函数接受数组作为参数，实际上执行的是下面的算法。
        const items2 = [
            ['name', '张三'],
            ['title', 'Author']
        ];
        const map2 = new Map()
        items2.forEach(([key, value]) => map2.set(key, value))
        console.log(map2)

        // Map.prototype.keys()： 返回键名的遍历器。
        // Map.prototype.values()： 返回键值的遍历器。
        // Map.prototype.entries()： 返回所有成员的遍历器。
        // Map.prototype.forEach()：遍历 Map 的所有成员。
        const map3 = new Map([
            ['F', 'no'],
            ['T', 'yes']
        ])
        for (let key of map3.keys()) {
            console.log(key)
        }

        for (let value of map3.values()) {
            console.log(value)
        }
        for (let item of map.entries()) {
            console.log(item[0], item[1])
        }

        for (let [key, value] of map3.entries()) {
            console.log(key, value)
        }

        for (let [key, value] of map3) {
            console.log(key, value)
        }


        // Map 结构转换为数组，比较快速的方法是使用扩展运算符
        const map4 = new Map([
            [1, 'one'],
            [2, 'two'],
            [3, 'three']
        ])
        console.log('---map 转 数组 ---')
        console.log(...map4.keys())
        console.log(...map4.values())
        console.log(...map4.entries())
        console.log(...map4)
    </script>
</body>

</html>